home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume16 / sipp2.0 / part03 < prev    next >
Encoding:
Internet Message Format  |  1991-01-02  |  54.2 KB

  1. From: kent@sparky.IMD.Sterling.COM (Kent Landfield)
  2. Newsgroups: comp.sources.misc
  3. Subject: v16i007:  sipp 2.0 - a library for 3D graphics, Part03/06
  4. Message-ID: <1991Jan3.065750.5109@sparky.IMD.Sterling.COM>
  5. Date: 3 Jan 91 06:57:50 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 1c94c058 ced62359 6fbe10b6 18ea05a5
  8.  
  9. Submitted-by: ingwa@isy.liu.se (Inge Wallin)
  10. Posting-number: Volume 16, Issue 7
  11. Archive-name: sipp2.0/part03
  12.  
  13. #!/bin/sh
  14. # This is part 03 of sipp-2.0
  15. # ============= libsipp/sipp.c ==============
  16. if test ! -d 'libsipp'; then
  17.     echo 'x - creating directory libsipp'
  18.     mkdir 'libsipp'
  19. fi
  20. if test -f 'libsipp/sipp.c' -a X"$1" != X"-c"; then
  21.     echo 'x - skipping libsipp/sipp.c (File already exists)'
  22. else
  23. echo 'x - extracting libsipp/sipp.c (Text)'
  24. sed 's/^X//' << 'SHAR_EOF' > 'libsipp/sipp.c' &&
  25. /*
  26. X * sipp - SImple Polygon Processor
  27. X *
  28. X *  A general 3d graphic package
  29. X *
  30. X *  Copyright Jonas Yngvesson  (jonas-y@isy.liu.se) 1988/89/90
  31. X *            Inge Wallin      (ingwa@isy.liu.se)         1990
  32. X *
  33. X * This program is free software; you can redistribute it and/or modify
  34. X * it under the terms of the GNU General Public License as published by
  35. X * the Free Software Foundation; either version 1, or any later version.
  36. X * This program is distributed in the hope that it will be useful,
  37. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39. X * GNU General Public License for more details.
  40. X * You can receive a copy of the GNU General Public License from the
  41. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  42. X * See the README for more information.
  43. X *
  44. X * Revision history:
  45. X *
  46. X * 901219  At last! 2.0 is out of the bag. And right in time for X-mas :-)
  47. X *         *Major* rewrite. A new level in the object hierarchy introduced.
  48. X *         An object is now a collection of surfaces and other objects
  49. X *         (subobjects). This allows creation of complex composite objects.
  50. X *         Objects in the hierarchy have coupled transformations.
  51. X *         The old "Object" is now, more appropriately, called Surface.
  52. X *         A fatal bug in the viewing transformation fixed.
  53. X *         Objects and surfaces have internal reference counters so deletion
  54. X *         won't leave dangling references in an hierachy.
  55. X *         The code is now almost readable.
  56. X *         Images format changed to PPM since much more applications
  57. X *         exists that can handle that format.
  58. X *         The shader package is extended and a package with functions
  59. X *         to create geometric primitives as objects is provided.
  60. X *
  61. X * 901030  More general shader interface. The simple internal shader
  62. X *         was moved out of sipp into its own file. Several shaders
  63. X *         provided together with it in a "shader package".
  64. X *
  65. X * 900712  Major code beautifying, quite a lot left to do though...
  66. X *         Typedefs instead of raw structures,
  67. X *         much better typenames, lots of comments added (probably
  68. X *         not enough though). Split into a few header files and
  69. X *         a source file. More portable interface.
  70. X *
  71. X * 891124  Made the object representation independent of the
  72. X *         illumination model used. A user can now supply his
  73. X *         own surface description and shading function.
  74. X *         Added support for texture mapping (both solid and 2d).
  75. X *         No texture mapping is built into the internal shader though.
  76. X *
  77. X * 891120  Added colour. New illumination model. Simple antialiasing
  78. X *         with double oversampling and a box filter.
  79. X *
  80. X * 891028  Converted from sippuz to sipp. Z-buffer changed 
  81. X *         to scan-line z-buffer.
  82. X *         Phong-shading.
  83. X *         The stack notion introduced.
  84. X *         Changed fixed viewpoint to a user defined one.
  85. X *         World coordinates and picture resolution can be chosen
  86. X *         freely.
  87. X *
  88. X * 881128  Converted from Pascal to C. Gouraud shading. Redesign of the
  89. X *         data structures.
  90. X *
  91. X * 88????  Original program "sippuz - simple polygon processing using a
  92. X *         z-buffer", written in Hedrick Pascal on a DEC-20 system
  93. X *         running TOPS-20. Greyscales only. Flat shading.
  94. X */
  95. X
  96. X
  97. #include <stdio.h>
  98. #include <math.h>
  99. #include <malloc.h>
  100. #ifndef NOMEMCPY
  101. #include <memory.h>
  102. #endif
  103. #include <xalloca.h>
  104. X
  105. #include <sipp.h>
  106. #include <sipptypes.h>
  107. #include <geometric.h>
  108. X
  109. X
  110. #define VERSION "2.0"
  111. X
  112. #define ZCLIPF 100.0        /* Magic number used when defining hither & yon */
  113. X
  114. X
  115. X
  116. /*
  117. X * Global variables.
  118. X */
  119. static Vertex      *vertex_tree;     /* Vertex tree for current object. */
  120. static Vertex_ref  *vertex_stack;    /* Vertex stack for current polygon. */
  121. static Vertex_ref  *vstack_bottom;   /* Last entry in vertex stack. */
  122. static Polygon     *poly_stack;      /* Polygon stack for current object. */
  123. static Inst_object *object_db;       /* Object database. */
  124. static Lightsource *lightsrc_stack;  /* Lightsource list. */
  125. static Bucket      *y_bucket;        /* Y-bucket for edge lists. */
  126. static double       dist_limit;      /* Minimal distance between two      */
  127. X                                     /* vertices without them being       */
  128. X                                     /* considered to be the same vertex. */
  129. static int          first_vertex;    /* Used when determining if we are   */
  130. X                                     /* installing the first vertex in an */
  131. X                                     /* object. *Not* a boolean!          */
  132. X
  133. /*
  134. X * Stack of transformation matrices used
  135. X * when traversing an object hierarchy.
  136. X */
  137. static struct tm_stack_t {
  138. X    Transf_mat         mat;
  139. X    struct tm_stack_t *next;
  140. } *tm_stack;
  141. X
  142. static Transf_mat      curr_mat;     /* Current transformation matrix */
  143. X
  144. static Transf_mat      ident_matrix = {{        /* Unit tranfs. matrix */
  145. X                           { 1.0, 0.0, 0.0 },
  146. X                           { 0.0, 1.0, 0.0 },
  147. X                           { 0.0, 0.0, 1.0 },
  148. X                           { 0.0, 0.0, 0.0 }
  149. X                       }};
  150. X
  151. X
  152. /*
  153. X * Viewpoint definition
  154. X */
  155. static struct {
  156. X    double x0, y0, z0;    /* viewpoint position */
  157. X    double x, y, z;       /* point to look at */
  158. X    Vector vec;           /* vector from point to eye, used in shading calc. */
  159. X    Vector up;            /* Up direction in the view */ 
  160. X    double focal_ratio;
  161. } camera;
  162. X
  163. X
  164. X
  165. /*======================== "Safe" malloc ================================*/
  166. static char *
  167. smalloc(size)
  168. X    int size;
  169. {
  170. X    char *p;
  171. X
  172. X    p = (char *)malloc(size);
  173. X    if (p == NULL) {
  174. X        fprintf(stderr, "Out of virtual memory.\n");
  175. X        exit(1);
  176. X    }
  177. X
  178. X    return p;
  179. }
  180. X
  181. X
  182. X
  183. /*================ Functions that handles lightsources ==================*/
  184. X
  185. /*
  186. X * Define a new lightsource in the scene.
  187. X */
  188. void
  189. lightsource_push(x, y, z, intensity)
  190. X    double  x, y, z, intensity;
  191. {
  192. X    double       norm;
  193. X    Lightsource *lp;
  194. X
  195. X    norm = sqrt(x * x + y * y + z * z);
  196. X    lp = (Lightsource *)smalloc(sizeof(Lightsource));
  197. X    lp->dir.x = x / norm;
  198. X    lp->dir.y = y / norm;
  199. X    lp->dir.z = z / norm;
  200. X    lp->intensity = intensity;
  201. X    lp->next = lightsrc_stack;
  202. X    lightsrc_stack = lp;
  203. }
  204. X
  205. X
  206. X
  207. /*================ Functions that handles the viewpoint ==================*/
  208. X
  209. /*
  210. X * Calculate the vector from the point of interest
  211. X * to the viewpoint. The shaders needs this vector normalized
  212. X * while the view coordinate transformation needs it
  213. X * non normalized, therefore we need this routine to
  214. X * recalculate the non normalized value.
  215. X */
  216. static void
  217. view_vec_eval()
  218. {
  219. X    MakeVector(camera.vec, 
  220. X               camera.x0 - camera.x, 
  221. X               camera.y0 - camera.y, 
  222. X               camera.z0 - camera.z);
  223. }
  224. X
  225. X
  226. X    
  227. /*
  228. X * Define the viewpoint.
  229. X */
  230. void
  231. view_from(x0, y0, z0)
  232. X    double x0, y0, z0;
  233. {
  234. X    camera.x0 = x0;
  235. X    camera.y0 = y0;
  236. X    camera.z0 = z0;
  237. X    view_vec_eval();
  238. }
  239. X
  240. X
  241. /*
  242. X * Define the point that we are looking at.
  243. X */
  244. void
  245. view_at(x, y, z)
  246. X    double x, y, z;
  247. {
  248. X    camera.x = x;
  249. X    camera.y = y;
  250. X    camera.z = z;
  251. X    view_vec_eval();
  252. }
  253. X
  254. X
  255. /*
  256. X * Define the "up" direction of the view (well, rather the y-z plane).
  257. X */
  258. void
  259. view_up(x, y, z)
  260. X    double x, y, z;
  261. {
  262. X    MakeVector(camera.up, x, y, z);
  263. }
  264. X
  265. X
  266. /*
  267. X * Set the focal ratio for the "camera".
  268. X */
  269. void
  270. view_focal(ratio)
  271. X    double ratio;
  272. {
  273. X    camera.focal_ratio = ratio;
  274. }
  275. X
  276. X
  277. /*
  278. X * Set all viewpoint parameters in one call.
  279. X */
  280. void
  281. viewpoint(x0, y0, z0, x, y, z, ux, uy, uz, ratio)
  282. X    double x0, y0, z0, x, y, z, ux, uy, uz, ratio;
  283. {
  284. X    camera.x0 = x0;
  285. X    camera.y0 = y0;
  286. X    camera.z0 = z0;
  287. X    camera.x = x;
  288. X    camera.y = y;
  289. X    camera.z = z;
  290. X    MakeVector(camera.up, ux, uy, uz);
  291. X    camera.focal_ratio = ratio;
  292. X    view_vec_eval();
  293. }
  294. X
  295. X
  296. X
  297. /*============= Functions that handles the object database ================*/
  298. X
  299. /*
  300. X * Search for a vertex in a vertex tree. Vertices are asumed
  301. X * to be equal if they differ less than dist_limit in all directions.
  302. X *
  303. X * If the vertex is not found, install it in the tree.
  304. X */
  305. static Vertex *
  306. vertex_lookup(x, y, z, u, v, w, p)
  307. X    double   x, y, z, u, v, w;
  308. X    Vertex **p;
  309. {
  310. X    double  xdist, ydist, zdist;
  311. X
  312. X    if (*p == NULL) {
  313. X        *p = (Vertex *)smalloc(sizeof(Vertex));
  314. X        (*p)->x = x;
  315. X        (*p)->y = y;
  316. X        (*p)->z = z;
  317. X        (*p)->a = 0;
  318. X        (*p)->b = 0;
  319. X        (*p)->c = 0;
  320. X        (*p)->u = u;
  321. X        (*p)->v = v;
  322. X        (*p)->w = w;
  323. X        (*p)->big = NULL;
  324. X        (*p)->sml = NULL;
  325. X        return *p;
  326. X    } else if ((xdist = x - ((*p)->x)) > dist_limit) {
  327. X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->big)));
  328. X    } else if (xdist < -dist_limit) {
  329. X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->sml)));
  330. X    } else if ((ydist = y - ((*p)->y)) > dist_limit) {
  331. X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->big)));
  332. X    } else if (ydist < -dist_limit) {
  333. X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->sml)));
  334. X    } else if ((zdist = z - ((*p)->z)) > dist_limit) {
  335. X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->big)));
  336. X    } else if (zdist < -dist_limit) {
  337. X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->sml)));
  338. X    } else {
  339. X        return *p;
  340. X    }
  341. }
  342. X
  343. X
  344. /*
  345. X * Push a vertex on the vertex stack (without texture coordinates).
  346. X */
  347. void
  348. vertex_push(x, y, z)
  349. X    double  x, y, z;
  350. {
  351. X    vertex_tx_push(x, y, z, (double)0.0, (double)0.0, (double)0.0);
  352. }
  353. X
  354. X
  355. /*
  356. X * Push a vertex on the vertex stack (with texture coordinates).
  357. X */
  358. void
  359. vertex_tx_push(x, y, z, u, v, w)
  360. X    double  x, y, z, u, v, w;
  361. {
  362. X    Vertex_ref *vref;
  363. X
  364. X   /* 
  365. X    * To get a reasonable dist_limit we use the following "heuristic" 
  366. X    * value:
  367. X    * The distance between the first two vertices installed in
  368. X    * the scene, multiplied by the magic number 1e-10, unless
  369. X    * they are the same vertex. In that case 1e-10 is used until
  370. X    * we get a vertex that differs from the first.
  371. X    */
  372. X    if (!first_vertex)
  373. X        first_vertex++;
  374. X    else if (first_vertex == 1) {
  375. X        dist_limit = sqrt((x - vertex_tree->x) * (x - vertex_tree->x)
  376. X                        + (y - vertex_tree->y) * (y - vertex_tree->y)
  377. X                        + (z - vertex_tree->z) * (z - vertex_tree->z))
  378. X                   * 1e-10;                      /* Magic!!! */
  379. X        if (dist_limit != 0.0)
  380. X            first_vertex++;
  381. X        else
  382. X            dist_limit = 1e-10;                  /* More Magic */
  383. X    }
  384. X    vref = (Vertex_ref *)smalloc(sizeof(Vertex_ref));
  385. X    if (vertex_stack == NULL) {
  386. X        vertex_stack = vref;
  387. X    } else {
  388. X        vstack_bottom->next = vref;
  389. X    }
  390. X    vstack_bottom = vref;
  391. X    vref->vertex = vertex_lookup(x, y, z, u, v, w, &vertex_tree);
  392. X    vref->next = NULL;
  393. }
  394. X
  395. X
  396. /*
  397. X * Push a polygon on the polygon stack. Empty the vertex stack afterwards.
  398. X */
  399. void
  400. polygon_push()
  401. {
  402. X    Polygon *polyref;
  403. X
  404. X    if (vertex_stack != NULL) {
  405. X        polyref = (Polygon *)smalloc(sizeof(Polygon));
  406. X        polyref->vertices = vertex_stack;
  407. X        polyref->backface = 0;
  408. X        polyref->next = poly_stack;
  409. X        poly_stack = polyref;
  410. X        vertex_stack = NULL;
  411. X    }
  412. }
  413. X
  414. X
  415. /*
  416. X * Create a surface of all polygons in the polygon stack.
  417. X * Empty the polygon stack afterwards.
  418. X */
  419. Surface *
  420. surface_create(surf_desc, shader)
  421. X    void   *surf_desc;
  422. X    Shader *shader;
  423. {
  424. X    Surface *surfref;
  425. X    
  426. X    if (poly_stack != NULL) {
  427. X        surfref = (Surface *)smalloc(sizeof(Surface));
  428. X        surfref->vertices = vertex_tree;
  429. X        surfref->polygons = poly_stack;
  430. X        surfref->surface = surf_desc;
  431. X        surfref->shader = shader;
  432. X        surfref->ref_count = 0;
  433. X        surfref->next = NULL;
  434. X        vertex_tree = NULL;
  435. X        poly_stack = NULL;
  436. X        first_vertex = 0;
  437. X        return surfref;
  438. X    } else
  439. X        return NULL;
  440. }
  441. X
  442. X
  443. /*
  444. X * Create a surface to be shaded with the simple shader.
  445. X */
  446. Surface *
  447. surface_basic_create(ambient, red, grn, blu, specular, c3)
  448. X    double ambient, red, grn, blu, specular, c3;
  449. {
  450. X    Surf_desc *surf_desc;
  451. X
  452. X    surf_desc = (Surf_desc *)smalloc(sizeof(Surf_desc));
  453. X    surf_desc->ambient = ambient;
  454. X    surf_desc->color.red = red;
  455. X    surf_desc->color.grn = grn;
  456. X    surf_desc->color.blu = blu;
  457. X    surf_desc->specular = specular;
  458. X    surf_desc->c3 = c3;
  459. X    return surface_create(surf_desc, basic_shader);
  460. }
  461. X
  462. X
  463. /*
  464. X * Set SURFACE to be shaded with the shading function SHADER
  465. X * using the surface description SURF_DESC.
  466. X */
  467. void
  468. surface_set_shader(surface, surf_desc, shader)
  469. X    Surface *surface;
  470. X    void    *surf_desc;
  471. X    Shader  *shader;
  472. {
  473. X    
  474. X    if (surface != NULL) {
  475. X        surface->surface = surf_desc;
  476. X        surface->shader = shader;
  477. X    }
  478. }
  479. X
  480. X
  481. /*
  482. X * Set SURFACE to be shaded with the simple shader.
  483. X */
  484. void
  485. surface_basic_shader(surface, ambient, red, grn, blu, specular, c3)
  486. X    Surface *surface;
  487. X    double  ambient, red, grn, blu, specular, c3;
  488. {
  489. X    Surf_desc *surf_desc;
  490. X
  491. X    surf_desc = (Surf_desc *)smalloc(sizeof(Surf_desc));
  492. X    surf_desc->ambient = ambient;
  493. X    surf_desc->color.red = red;
  494. X    surf_desc->color.grn = grn;
  495. X    surf_desc->color.blu = blu;
  496. X    surf_desc->specular = specular;
  497. X    surf_desc->c3 = c3;
  498. X    surface_set_shader(surface, surf_desc, basic_shader);
  499. }
  500. X
  501. X
  502. X
  503. /*
  504. X * Copy a vertex tree.
  505. X */
  506. static Vertex *
  507. copy_vertices(vp)
  508. X    Vertex *vp;
  509. {
  510. X    Vertex *tmp;
  511. X
  512. X    if (vp == NULL)
  513. X        return NULL;
  514. X    tmp = (Vertex *)smalloc(sizeof(Vertex));
  515. X    *tmp = *vp;
  516. X    tmp->big = copy_vertices(vp->big);
  517. X    tmp->sml = copy_vertices(vp->sml);
  518. X    return tmp;
  519. }
  520. X
  521. X
  522. /*
  523. X * We have a list of vertes references, each pointing into a certain
  524. X * vertex tree. Create a new list with pointers into a copy of the
  525. X * first vertex tree.
  526. X */
  527. static Vertex_ref *
  528. copy_vlist(vp, surface)
  529. X    Vertex_ref *vp;
  530. X    Surface    *surface;
  531. {
  532. X    Vertex_ref *tmp;
  533. X    
  534. X    if (vp == NULL)
  535. X        return NULL;
  536. X    tmp = (Vertex_ref *)smalloc(sizeof(Vertex_ref));
  537. X    tmp->vertex = vertex_lookup(vp->vertex->x, vp->vertex->y, vp->vertex->z,
  538. X                                vp->vertex->u, vp->vertex->v, vp->vertex->w,
  539. X                                &(surface->vertices));
  540. X    tmp->next = copy_vlist(vp->next, surface);
  541. X    return tmp;
  542. }
  543. X
  544. X
  545. /*
  546. X * Copy a list of polygons.
  547. X */
  548. static Polygon *
  549. copy_polygons(pp, surface)
  550. X    Polygon *pp;
  551. X    Surface *surface;
  552. {
  553. X    Polygon *tmp;
  554. X
  555. X    if (pp == NULL)
  556. X        return NULL;
  557. X    tmp = (Polygon *)smalloc(sizeof(Polygon));
  558. X    tmp->vertices = copy_vlist(pp->vertices, surface);
  559. X    tmp->next = copy_polygons(pp->next, surface);
  560. X    return tmp;
  561. }
  562. X
  563. X
  564. /*
  565. X * Copy a list of surfaces. All polygons and vertices are copied but
  566. X * the shader and surface descriptions are the same as in the
  567. X * original surfaces.
  568. X */
  569. static Surface *
  570. surface_copy(surface)
  571. X    Surface  *surface;
  572. {
  573. X    Surface  *newsurf;
  574. X
  575. X    if (surface != NULL) {
  576. X        newsurf = (Surface *)smalloc(sizeof(Surface));
  577. X        if (newsurf == NULL) {
  578. X            return NULL;
  579. X        }
  580. X        memcpy(newsurf, surface, sizeof(Surface));
  581. X        newsurf->vertices = copy_vertices(surface->vertices);
  582. X        newsurf->polygons = copy_polygons(surface->polygons, newsurf);
  583. X        newsurf->ref_count = 1;
  584. X        newsurf->next = surface_copy(surface->next);
  585. X        return newsurf;
  586. X    } else {
  587. X        return NULL;
  588. X    }
  589. }
  590. X
  591. X
  592. /*
  593. X * Delete a vertex tree.
  594. X */
  595. static void
  596. delete_vertices(vtree)
  597. X    Vertex **vtree;
  598. {
  599. X    if (*vtree != NULL) {
  600. X        delete_vertices(&((*vtree)->big));
  601. X        delete_vertices(&((*vtree)->sml));
  602. X        free(*vtree);
  603. X        *vtree = NULL;
  604. X    }
  605. }
  606. X
  607. X
  608. /*
  609. X * Delete a surface list.
  610. X */
  611. static void
  612. surface_delete(surface)
  613. X    Surface *surface;
  614. {
  615. X    Vertex_ref *vref1, *vref2;
  616. X    Polygon    *polyref1, *polyref2;
  617. X
  618. X    if (surface != NULL) {
  619. X        if (--surface->ref_count == 0) {
  620. X            if (surface->next != NULL) {
  621. X                surface_delete(surface->next);
  622. X            }
  623. X            polyref2 = surface->polygons;
  624. X            while (polyref2 != NULL) {
  625. X                vref2 = polyref2->vertices;
  626. X                while (vref2 != NULL) {
  627. X                    vref1 = vref2;
  628. X                    vref2 = vref2->next;
  629. X                    free(vref1);
  630. X                }
  631. X                polyref1 = polyref2;
  632. X                polyref2 = polyref2->next;
  633. X                free(polyref1);
  634. X            }
  635. X            delete_vertices(&(surface->vertices));
  636. X            free(surface);
  637. X        }
  638. X    }
  639. }
  640. X
  641. X
  642. /*
  643. X * Install an object in the rendering database.
  644. X */
  645. static void
  646. r_object_install(obj, obj_tree)
  647. X    Object       *obj;
  648. X    Inst_object **obj_tree;
  649. {
  650. X    if (obj != NULL) {
  651. X        obj->ref_count++;
  652. X        if (*obj_tree == NULL) {
  653. X            *obj_tree = (Inst_object *)smalloc(sizeof(Inst_object));
  654. X            (*obj_tree)->object = obj;
  655. X            (*obj_tree)->big = NULL;
  656. X            (*obj_tree)->sml = NULL;
  657. X        } else if (obj > (*obj_tree)->object) {
  658. X            r_object_install(obj, &(*obj_tree)->big);
  659. X        } else if (obj < (*obj_tree)->object) {
  660. X            r_object_install(obj, &(*obj_tree)->sml);
  661. X        }
  662. X    }
  663. }
  664. X
  665. X
  666. /*
  667. X * Interface to r_object_install(). (Why is there no
  668. X * subfunctions in C?...)
  669. X */
  670. void
  671. object_install(obj)
  672. X    Object *obj;
  673. {
  674. X    r_object_install(obj, &object_db);
  675. }
  676. X
  677. X
  678. X
  679. /*
  680. X * Subfunction to r_object_uninstall.
  681. X */
  682. static void
  683. r_del(r, q)
  684. X    Inst_object **r;
  685. X    Inst_object  *q;
  686. {
  687. X    if ((*r)->big != NULL) {
  688. X        r_del(&((*r)->big), q);
  689. X    } else {
  690. X        q->object = (*r)->object;
  691. X        q = *r;
  692. X        *r = (*r)->sml;
  693. X        free(q);
  694. X    }
  695. }
  696. X
  697. X
  698. /*
  699. X * Delete an object from the rendering database.
  700. X * The object itself is not deleted of course.
  701. X */
  702. static void
  703. r_object_uninstall(obj, root)
  704. X    Object       *obj;
  705. X    Inst_object **root;
  706. {
  707. X    Inst_object *ptr;
  708. X
  709. X    if (*root == NULL) {
  710. X        return;            /* Object is not in the tree */
  711. X    } else if (obj < (*root)->object) {
  712. X        r_object_uninstall(obj, &(*root)->sml);
  713. X    } else if (obj > (*root)->object) {
  714. X        r_object_uninstall(obj, &(*root)->big);
  715. X    } else {
  716. X        obj->ref_count--;
  717. X        ptr = *root;
  718. X        if (ptr->big == NULL) {
  719. X            *root = ptr->sml;
  720. X        } else if (ptr->sml == NULL) {
  721. X            *root = ptr->big;
  722. X        } else {
  723. X            r_del(&ptr->sml, ptr);
  724. X        }
  725. X    }
  726. }
  727. X    
  728. X    
  729. /*
  730. X * Interface to r_object_uninstall.
  731. X */
  732. void
  733. object_uninstall(obj)
  734. X    Object *obj;
  735. {
  736. X    r_object_uninstall(obj, &object_db);
  737. }
  738. X
  739. X
  740. X
  741. /*
  742. X * Create an empty object. Before it is rendered it
  743. X * must get a surface or a subobject. 
  744. X */
  745. Object *
  746. object_create()
  747. {
  748. X    Object *obj;
  749. X
  750. X    obj = (Object *)smalloc(sizeof(Object));
  751. X    obj->surfaces = NULL;
  752. X    obj->sub_obj = NULL;
  753. X    MatCopy(&obj->transf, &ident_matrix);
  754. X    obj->ref_count = 0;
  755. X    obj->next = NULL;
  756. X
  757. X    return obj;
  758. }
  759. X
  760. X
  761. X
  762. /*
  763. X * Copy the top object in an object hierarchy.
  764. X * The new object will reference the same
  765. X * subobjects and surfaces as the original object.
  766. X * if REF_COUNT_UPDATE is true, the reference counts
  767. X * in the surfaces and subobjects will be incremented.
  768. X */
  769. static Object *
  770. object_copy(object, ref_count_update)
  771. X    Object *object;
  772. X    bool    ref_count_update;
  773. {
  774. X    Object *newobj;
  775. X
  776. X    if (object == NULL) {
  777. X        return NULL;
  778. X    }
  779. X
  780. X    if ((newobj = (Object *)smalloc(sizeof(Object))) != NULL) {
  781. X        memcpy(newobj, object, sizeof(Object));
  782. X        if (ref_count_update) {
  783. X            if (newobj->sub_obj != NULL) {
  784. X                newobj->sub_obj->ref_count++;
  785. X            }
  786. X            if (newobj->surfaces != NULL) {
  787. X                newobj->surfaces->ref_count++;
  788. X            }
  789. X        }
  790. X        MatCopy(&newobj->transf, &ident_matrix);
  791. X        newobj->ref_count = 0;
  792. X        newobj->next = NULL;
  793. X    }
  794. X
  795. X    return newobj;
  796. }
  797. X
  798. X
  799. /*
  800. X * Copy a list of objects. If SURF_COPY is true
  801. X * the surfaces in the objects will be copied too.
  802. X */
  803. static Object *
  804. object_list_copy(object, surf_copy)
  805. X    Object *object;
  806. X    bool    surf_copy;
  807. {
  808. X    Object *newobj;
  809. X
  810. X    if (object == NULL) {
  811. X        return NULL;
  812. X    }
  813. X
  814. X    if ((newobj = (Object *)smalloc(sizeof(Object))) != NULL) {
  815. X        memcpy(newobj, object, sizeof(Object));
  816. X        newobj->ref_count = 0;
  817. X    } else {
  818. X        return NULL;
  819. X    }
  820. X
  821. X    if (surf_copy) {
  822. X        newobj->surfaces = surface_copy(object->surfaces);
  823. X    } else if (newobj->surfaces != NULL){
  824. X        newobj->surfaces->ref_count++;
  825. X    }
  826. X
  827. X    newobj->sub_obj = object_list_copy(object->sub_obj, surf_copy);
  828. X    if (newobj->sub_obj != NULL) {
  829. X        newobj->sub_obj->ref_count++;
  830. X    }
  831. X    newobj->next = object_list_copy(object->next, surf_copy);
  832. X    if (newobj->next != NULL) {
  833. X        newobj->next->ref_count++;
  834. X    }
  835. X
  836. X    return newobj;
  837. }
  838. X    
  839. X
  840. X
  841. /*
  842. X * Copy the top node of an object hierarchy. The
  843. X * subobjects and surface references will be the
  844. X * same as in the original.
  845. X */
  846. Object *
  847. object_instance(obj)
  848. X    Object *obj;
  849. {
  850. X    return object_copy(obj, TRUE);
  851. }
  852. X
  853. X
  854. X
  855. /*
  856. X * Copy an object hierarchy. The objects in
  857. X * the new hierarchy will reference the same
  858. X * surfaces as the object in
  859. X * the old hierarchy, but all object nodes
  860. X * will be duplicated.
  861. X */
  862. Object *
  863. object_dup(object)
  864. X    Object *object;
  865. {
  866. X    Object *newobj;
  867. X
  868. X    if ((newobj = object_copy(object, FALSE)) == NULL) {
  869. X        return NULL;
  870. X    }
  871. X
  872. X    newobj->sub_obj = object_list_copy(object->sub_obj, FALSE);
  873. X    newobj->next = NULL;
  874. X
  875. X    return newobj;
  876. }
  877. X
  878. X
  879. /*
  880. X * Copy an object hierarchy. All object nodes
  881. X * and surfaces in the old hierarchy
  882. X * will be duplicated.
  883. X */
  884. Object *
  885. object_deep_dup(object)
  886. X    Object *object;
  887. {
  888. X    Object *newobj;
  889. X
  890. X    if ((newobj = object_copy(object, FALSE)) == NULL) {
  891. X        return NULL;
  892. X    }
  893. X
  894. X    newobj->surfaces = surface_copy(object->surfaces);
  895. X    newobj->sub_obj = object_list_copy(object->sub_obj, TRUE);
  896. X    newobj->next = NULL;
  897. X
  898. X    return newobj;
  899. }
  900. X
  901. X
  902. X
  903. /*
  904. X * Recursively delete an object hierarchy. Reference
  905. X * counts are decremented and if the result is zero
  906. X * the recursion continues and the memory used is freed.
  907. X */
  908. static void
  909. r_object_delete(object)
  910. X    Object * object;
  911. {
  912. X    if (object != NULL) {
  913. X        if (--object->ref_count == 0) {
  914. X            surface_delete(object->surfaces);
  915. X            r_object_delete(object->sub_obj);
  916. X            r_object_delete(object->next);
  917. X            free(object);
  918. X        }
  919. X    }
  920. }
  921. X
  922. X
  923. X
  924. /*
  925. X * Delete an object hierarchy. This is only possible
  926. X * to do on a top level object.
  927. X */
  928. void
  929. object_delete(object)
  930. X    Object * object;
  931. {
  932. X    if (object != NULL) {
  933. X        if (object->ref_count == 0) {         /* Is it a top level object? */
  934. X            surface_delete(object->surfaces);
  935. X            r_object_delete(object->sub_obj);
  936. X            r_object_delete(object->next);
  937. X            free(object);
  938. X        }
  939. X    }
  940. }
  941. X
  942. X
  943. X
  944. /*
  945. X * Add SUBOBJ as a subobject in OBJECT. SUBOBJ is appended
  946. X * on the *end* of OBJECT's subobject list, 
  947. X * so that if SUBOBJ, for some obscure reason, 
  948. X * were the head of an object list, we don't loose
  949. X * the rest of that list. 
  950. X * Remove SUBOBJ from the rendering database since it is no
  951. X * longer a root object in an hierarchy.
  952. X */
  953. void
  954. object_add_subobj(object, subobj)
  955. X    Object *object, *subobj;
  956. {
  957. X    Object *oref;
  958. X
  959. X    if (object == NULL || subobj == NULL) {
  960. X        return;
  961. X    }
  962. X
  963. X    if (object->sub_obj == NULL) {
  964. X        object->sub_obj = subobj;
  965. X    } else {
  966. X        oref = object->sub_obj;
  967. X        while (oref->next != NULL) {
  968. X            oref = oref->next;
  969. X        }
  970. X        oref->next = subobj;
  971. X    }
  972. X
  973. X    subobj->ref_count++;
  974. X    object_uninstall(subobj);
  975. }
  976. X
  977. X
  978. X
  979. /*
  980. X * Add SURFACE to the list of surfaces belonging
  981. X * to OBJECT. SURFACE is appended on the *end* of the
  982. X * list for the same reasons as in object_add_subobj.
  983. X */
  984. void
  985. object_add_surface(object, surface)
  986. X    Object  *object;
  987. X    Surface *surface;
  988. {
  989. X    Surface *sref;
  990. X
  991. X    if (object == NULL || surface == NULL) {
  992. X        return;
  993. X    }
  994. X
  995. X    if (object->surfaces == NULL) {
  996. X        object->surfaces = surface;
  997. X    } else {
  998. X        sref = object->surfaces;
  999. X        while (sref->next != NULL) {
  1000. X            sref = sref->next;
  1001. X        }
  1002. X        sref->next = surface;
  1003. X    }
  1004. X
  1005. X    surface->ref_count++;
  1006. }
  1007. X    
  1008. X    
  1009. X    
  1010. X    
  1011. /*============= Functions that handles object transformations==============*/
  1012. X
  1013. /*
  1014. X * Set the transformation matrix of OBJ to MATRIX.
  1015. X */
  1016. void
  1017. object_set_transf(obj, matrix)
  1018. X    Object     *obj;
  1019. X    Transf_mat *matrix;
  1020. {
  1021. X    MatCopy(&obj->transf, matrix);
  1022. }
  1023. X
  1024. X
  1025. /*
  1026. X * Set the transformation matrix of OBJ to the identity matrix.
  1027. X */
  1028. void
  1029. object_clear_transf(obj)
  1030. X    Object *obj;
  1031. {
  1032. X    MatCopy(&obj->transf, &ident_matrix);
  1033. }
  1034. X
  1035. X
  1036. /*
  1037. X * Post multiply MATRIX into the transformation matrix of OBJ.
  1038. X */
  1039. void
  1040. object_transform(obj, matrix)
  1041. X    Object     *obj;
  1042. X    Transf_mat *matrix;
  1043. {
  1044. X    mat_mul(&obj->transf, &obj->transf, matrix);
  1045. }
  1046. X
  1047. X
  1048. /*
  1049. X * Rotate the object OBJ ANG radians about the x-axis.
  1050. X */
  1051. void
  1052. object_rot_x(obj, ang)
  1053. X    Object *obj;
  1054. X    double  ang;
  1055. {
  1056. X    mat_rotate_x(&obj->transf, ang);
  1057. }
  1058. X
  1059. X
  1060. /*
  1061. X * Rotate the object OBJ ANG radians about the y-axis.
  1062. X */
  1063. void
  1064. object_rot_y(obj, ang)
  1065. X    Object *obj;
  1066. X    double  ang;
  1067. {
  1068. X    mat_rotate_y(&obj->transf, ang);
  1069. }
  1070. X
  1071. X
  1072. /*
  1073. X * Rotate the object OBJ ANG radians about the z-axis.
  1074. X */
  1075. void
  1076. object_rot_z(obj, ang)
  1077. X    Object *obj;
  1078. X    double  ang;
  1079. {
  1080. X    mat_rotate_z(&obj->transf, ang);
  1081. }
  1082. X
  1083. X
  1084. /*
  1085. X * Rotate the object OBJ ANG radians about the line defined
  1086. X * by POINT and VEC.
  1087. X */
  1088. void
  1089. object_rot(obj, point, vec, ang)
  1090. X    Object *obj;
  1091. X    Vector *point;
  1092. X    Vector *vec;
  1093. X    double  ang;
  1094. {
  1095. X    mat_rotate(&obj->transf, point, vec, ang);
  1096. }
  1097. X
  1098. X
  1099. /*
  1100. X * Scale the object OBJ with respect to the origin.
  1101. X */
  1102. void
  1103. object_scale(obj, xscale, yscale, zscale)
  1104. X    Object *obj;
  1105. X    double  xscale, yscale, zscale;
  1106. {
  1107. X    mat_scale(&obj->transf, xscale, yscale, zscale);
  1108. }
  1109. X
  1110. X
  1111. /*
  1112. X * Translate the object OBJ.
  1113. X */
  1114. void
  1115. object_move(obj, dx, dy, dz)
  1116. X    Object *obj;
  1117. X    double  dx, dy, dz;
  1118. {
  1119. X    mat_translate(&obj->transf, dx, dy, dz);
  1120. }
  1121. X
  1122. X
  1123. X
  1124. X
  1125. /*============= Functions that handles rendering of the scene==============*/
  1126. X
  1127. X
  1128. /*
  1129. X * Calculate the normal vector for all polygons in the polygon list PSTART.
  1130. X *
  1131. X * Check if the polygon is backfacing with respect to the current
  1132. X * viewpoint.
  1133. X *
  1134. X * The normalized normal is added to a normal kept at each vertex
  1135. X * in the polygon. This will produce, at each vertex, an average of the
  1136. X * normals of the adjectent plygons.
  1137. X */
  1138. static void
  1139. calc_normals(pstart, eyepoint)
  1140. X    Polygon *pstart;    /* Head of polygon list */
  1141. X    Vector   eyepoint;  /* Viewpoint transformed to local coordinate system */
  1142. {
  1143. X    Vector      normal;
  1144. X    Vertex_ref *vref1, *vref2;
  1145. X    Polygon    *polyref;
  1146. X    double      plane_const;
  1147. X
  1148. X    for (polyref = pstart; polyref != NULL; polyref = polyref->next) {
  1149. X        vref1 = polyref->vertices;
  1150. X        vref2 = vref1->next;
  1151. X
  1152. X        normal.x = normal.y = normal.z = 0.0;
  1153. X        do {
  1154. X            normal.x += ((vref1->vertex->y - vref2->vertex->y)
  1155. X                         * (vref1->vertex->z + vref2->vertex->z));
  1156. X            normal.y += ((vref1->vertex->z - vref2->vertex->z)
  1157. X                         * (vref1->vertex->x + vref2->vertex->x));
  1158. X            normal.z += ((vref1->vertex->x - vref2->vertex->x)
  1159. X                         * (vref1->vertex->y + vref2->vertex->y));
  1160. X            vref1 = vref1->next;
  1161. X            vref2 = ((vref2->next == NULL)?polyref->vertices:vref2->next);
  1162. X        } while (vref1 != NULL);
  1163. X        vecnorm(&normal);
  1164. X
  1165. X        plane_const = -(normal.x * vref2->vertex->x
  1166. X                        + normal.y * vref2->vertex->y
  1167. X                        + normal.z * vref2->vertex->z);
  1168. X        if (VecDot(eyepoint, normal) + plane_const <= 0.0) {
  1169. X            polyref->backface = TRUE;
  1170. X        } else {
  1171. X            polyref->backface = FALSE;
  1172. X        }
  1173. X            
  1174. X        for (vref1 = polyref->vertices; vref1 != NULL; vref1 = vref1->next) {
  1175. X            vref1->vertex->a += normal.x;
  1176. X            vref1->vertex->b += normal.y;
  1177. X            vref1->vertex->c += normal.z;
  1178. X        }
  1179. X    }
  1180. }
  1181. X
  1182. X
  1183. X
  1184. /*
  1185. X * Walk around a polygon, create the surrounding
  1186. X * edges and sort them into the y-bucket.
  1187. X * Clip polygons in y at the same time.
  1188. X */
  1189. static void
  1190. create_edges(view_vert, yres, polygon, surface)
  1191. X    View_coord *view_vert;
  1192. X    int         yres;
  1193. X    int         polygon;
  1194. X    Surface    *surface;
  1195. {
  1196. X    Edge       *edge;
  1197. X    View_coord *view_ref, *last;
  1198. X    int         nderiv, y1, y2, ymax;
  1199. X    int         clip1, clip2;
  1200. X    double      deltay, ratio;
  1201. X    double      x1, x2, xstep;
  1202. X    double      z1, z2, zstep;
  1203. X    double      nx1, nx2, nxstep;
  1204. X    double      ny1, ny2, nystep;
  1205. X    double      nz1, nz2, nzstep;
  1206. X    double      u1, u2, ustep;
  1207. X    double      v1, v2, vstep;
  1208. X    double      w1, w2, wstep;
  1209. X
  1210. X    view_ref = last = view_vert;
  1211. X    ymax = yres - 1;
  1212. X    do {
  1213. X        view_ref = view_ref->next;
  1214. X        x1 = view_ref->x;
  1215. X        x2 = view_ref->next->x;
  1216. X        y1 = view_ref->y;
  1217. X        y2 = view_ref->next->y;
  1218. X        z1 = view_ref->z;
  1219. X        z2 = view_ref->next->z;
  1220. X        nx1 = view_ref->nx;
  1221. X        nx2 = view_ref->next->nx;
  1222. X        ny1 = view_ref->ny;
  1223. X        ny2 = view_ref->next->ny;
  1224. X        nz1 = view_ref->nz;
  1225. X        nz2 = view_ref->next->nz;
  1226. X        u1 = view_ref->u;
  1227. X        u2 = view_ref->next->u;
  1228. X        v1 = view_ref->v;
  1229. X        v2 = view_ref->next->v;
  1230. X        w1 = view_ref->w;
  1231. X        w2 = view_ref->next->w;
  1232. X        clip1 = (y1 < 0) + ((y1 > ymax) << 1);
  1233. X        clip2 = (y2 < 0) + ((y2 > ymax) << 1);
  1234. X        if (!(clip1 & clip2)) {
  1235. X            if (clip1 != 0) {
  1236. X                if (clip1 == 1)
  1237. X                    ratio = (0.0 - (double)y1) / (double)(y2 - y1);
  1238. X                else 
  1239. X                    ratio = (double)(ymax - y1) / (double)(y2 - y1);
  1240. X                x1 = x1 + ratio * (x2 - x1);
  1241. X                y1 = y1 + ratio * (y2 - y1);
  1242. X                z1 = z1 + ratio * (z2 - z1);
  1243. X                nx1 = nx1 + ratio * (nx2 - nx1);
  1244. X                ny1 = ny1 + ratio * (ny2 - ny1);
  1245. X                nz1 = nz1 + ratio * (nz2 - nz1);
  1246. X                u1 = u1 + ratio * (u2 - u1);
  1247. X                v1 = v1 + ratio * (v2 - v1);
  1248. X                w1 = w1 + ratio * (w2 - w1);
  1249. X            }
  1250. X            if (clip2 != 0) {
  1251. X                if (clip2 == 1)
  1252. X                    ratio = (0.0 - (double)y2) / (double)(y1 - y2);
  1253. X                else 
  1254. X                    ratio = (double)(ymax - y2) / (double)(y1 - y2);
  1255. X                x2 = x2 + ratio * (x1 - x2);
  1256. X                y2 = y2 + ratio * (y1 - y2);
  1257. X                z2 = z2 + ratio * (z1 - z2);
  1258. X                nx2 = nx2 + ratio * (nx1 - nx2);
  1259. X                ny2 = ny2 + ratio * (ny1 - ny2);
  1260. X                nz2 = nz2 + ratio * (nz1 - nz2);
  1261. X                u2 = u2 + ratio * (u1 - u2);
  1262. X                v2 = v2 + ratio * (v1 - v2);
  1263. X                w2 = w2 + ratio * (w1 - w2);
  1264. X            }
  1265. X            deltay = (double)(y2 - y1);
  1266. X            if (deltay > 0.0)
  1267. X            nderiv = 1;
  1268. X        else if (deltay < 0.0)
  1269. X            nderiv = -1;
  1270. X        else
  1271. X            nderiv = 0;
  1272. X            if (nderiv) {
  1273. X            deltay = fabs(deltay);
  1274. X                xstep = (x2 - x1) / deltay;
  1275. X                zstep = (z2 - z1) / deltay;
  1276. X                nxstep = (nx2 - nx1) / deltay;
  1277. X                nystep = (ny2 - ny1) / deltay;
  1278. X                nzstep = (nz2 - nz1) / deltay;
  1279. X                ustep = (u2 - u1) / deltay;
  1280. X                vstep = (v2 - v1) / deltay;
  1281. X                wstep = (w2 - w1) / deltay;
  1282. X                edge = (Edge *)smalloc(sizeof(Edge));
  1283. X                if (nderiv > 0) {
  1284. X                    edge->y = y2;
  1285. X                    edge->y_stop = y1;
  1286. X                    edge->x = x2;
  1287. X                    edge->z = z2;
  1288. X                    edge->nx = nx2;
  1289. X                    edge->ny = ny2;
  1290. X                    edge->nz = nz2;
  1291. X                    edge->u = u2;
  1292. X                    edge->v = v2;
  1293. X                    edge->w = w2;
  1294. X                    edge->xstep = -xstep;
  1295. X                    edge->zstep = -zstep;
  1296. X                    edge->nxstep = -nxstep;
  1297. X                    edge->nystep = -nystep;
  1298. X                    edge->nzstep = -nzstep;
  1299. X                    edge->ustep = -ustep;
  1300. X                    edge->vstep = -vstep;
  1301. X                    edge->wstep = -wstep;
  1302. X                } else {
  1303. X                    edge->y = y1;
  1304. X                    edge->y_stop = y2;
  1305. X                    edge->x = x1;
  1306. X                    edge->z = z1;
  1307. X                    edge->nx = nx1;
  1308. X                    edge->ny = ny1;
  1309. X                    edge->nz = nz1;
  1310. X                    edge->u = u1;
  1311. X                    edge->v = v1;
  1312. X                    edge->w = w1;
  1313. X                    edge->xstep = xstep;
  1314. X                    edge->zstep = zstep;
  1315. X                    edge->nxstep = nxstep;
  1316. X                    edge->nystep = nystep;
  1317. X                    edge->nzstep = nzstep;
  1318. X                    edge->ustep = ustep;
  1319. X                    edge->vstep = vstep;
  1320. X                    edge->wstep = wstep;
  1321. X                }
  1322. X            } else {
  1323. X                zstep = (z2 - z1) / fabs(x2 - x1);
  1324. X                edge = (Edge *)smalloc(sizeof(Edge));
  1325. X                edge->y = y2;
  1326. X                edge->y_stop = y1;
  1327. X                if (x1 < x2) {
  1328. X                    edge->x = x1;
  1329. X                    edge->z = z1;
  1330. X                    edge->xstep = x2;
  1331. X                    edge->zstep = zstep;
  1332. X                } else {
  1333. X                    edge->x = x2;
  1334. X                    edge->z = z2;
  1335. X                    edge->xstep = x1;
  1336. X                    edge->zstep = -zstep;
  1337. X                }
  1338. X            }
  1339. X            edge->polygon = polygon;
  1340. X            edge->surface = surface;
  1341. X            edge->next = NULL;
  1342. X            if (y_bucket[edge->y].last == NULL) {
  1343. X                y_bucket[edge->y].first = edge;
  1344. X                y_bucket[edge->y].last = edge;
  1345. X            } else {
  1346. X                y_bucket[edge->y].last->next = edge;
  1347. X                y_bucket[edge->y].last = edge;
  1348. X            }
  1349. X        }
  1350. X    } while (view_ref != last);
  1351. }
  1352. X
  1353. X
  1354. /*
  1355. X * Transform vertices into view coordinates. The transform is
  1356. X * defined in MATRIX. Store the transformed vertices in a
  1357. X * temporary list, create edges in the y_bucket.
  1358. X */
  1359. static void
  1360. transf_vertices(vertex_list, surface, matrix, tr_mat, xsiz, ysiz)
  1361. X    Vertex_ref *vertex_list;
  1362. X    Surface    *surface;
  1363. X    double      matrix[4][4];
  1364. X    Transf_mat *tr_mat;
  1365. X    double      xsiz, ysiz;
  1366. {
  1367. X    static int  polygon = 0;        /* incremented for each call to provide */
  1368. X                                    /* unique polygon id numbers */
  1369. X    Vertex_ref *vref;
  1370. X    View_coord *view_ref, *nhead, *ntail;
  1371. X    double      minsize;
  1372. X    double      w, tmp;
  1373. X    bool        first, last;
  1374. X
  1375. X    first = TRUE;
  1376. X    last = FALSE;
  1377. X    vref = vertex_list;
  1378. X    nhead = NULL;
  1379. X
  1380. X    minsize = ((xsiz > ysiz) ? ysiz : xsiz);
  1381. X
  1382. X    while ((vref != NULL) && !last) {
  1383. X
  1384. X        view_ref = (View_coord *)alloca(sizeof(View_coord));
  1385. X        last = (vref->next == NULL);
  1386. X
  1387. X        view_ref->nx = (vref->vertex->a * tr_mat->mat[0][0] 
  1388. X                        + vref->vertex->b * tr_mat->mat[1][0] 
  1389. X                        + vref->vertex->c * tr_mat->mat[2][0]);
  1390. X        view_ref->ny = (vref->vertex->a * tr_mat->mat[0][1] 
  1391. X                        + vref->vertex->b * tr_mat->mat[1][1] 
  1392. X                        + vref->vertex->c * tr_mat->mat[2][1]);
  1393. X        view_ref->nz = (vref->vertex->a * tr_mat->mat[0][2] 
  1394. X                        + vref->vertex->b * tr_mat->mat[1][2] 
  1395. X                        + vref->vertex->c * tr_mat->mat[2][2]);
  1396. X
  1397. X        w = vref->vertex->x * matrix[0][3] + vref->vertex->y * matrix[1][3] +
  1398. X        vref->vertex->z * matrix[2][3] + matrix[3][3];
  1399. X        view_ref->x = ((vref->vertex->x * matrix[0][0] 
  1400. X                        + vref->vertex->y * matrix[1][0] 
  1401. X                        + vref->vertex->z * matrix[2][0]
  1402. X                        + matrix[3][0]) * minsize / w + xsiz);
  1403. X        tmp         = ((vref->vertex->x * matrix[0][1] 
  1404. X                        + vref->vertex->y * matrix[1][1] 
  1405. X                        + vref->vertex->z * matrix[2][1]
  1406. X                        + matrix[3][1]) * minsize / w + ysiz) ;
  1407. X
  1408. X        view_ref->y = (int)(tmp + 0.5);
  1409. X        view_ref->z = (vref->vertex->x * matrix[0][2] + vref->vertex->y *
  1410. X                       matrix[1][2] + vref->vertex->z * matrix[2][2] +
  1411. X                       matrix[3][2]) / w; 
  1412. X
  1413. X        view_ref->u = vref->vertex->u;
  1414. X        view_ref->v = vref->vertex->v;
  1415. X        view_ref->w = vref->vertex->w;
  1416. X        view_ref->next = nhead;
  1417. X        nhead = view_ref;
  1418. X
  1419. X        if (first) {
  1420. X            ntail = view_ref;
  1421. X            first = FALSE;
  1422. X        }
  1423. X        if (!last)
  1424. X            vref = vref->next;
  1425. X    }
  1426. X
  1427. X    ntail->next = nhead;
  1428. X    create_edges(nhead, (int)ysiz << 1, polygon++, surface);
  1429. }
  1430. X
  1431. X
  1432. /*
  1433. X * Initialize the scanline z-buffer and the actual picture
  1434. X * scanline buffer.
  1435. X */
  1436. static void
  1437. init_buffers(res, z_buffer, scanline)
  1438. X    int            res;
  1439. X    double        *z_buffer;
  1440. X    unsigned char *scanline;
  1441. {
  1442. X    int i;
  1443. X    
  1444. #ifdef NOMEMCPY
  1445. X    bzero(scanline, res * 3);
  1446. #else
  1447. X    memset(scanline, 0, res * 3);
  1448. #endif
  1449. X    for (i = 0; i < res; i++)
  1450. X        z_buffer[i] = 2.0;
  1451. }
  1452. X    
  1453. X
  1454. /*
  1455. X * Read edge pairs from the edge list EDGE_LIST. Walk along the scanline
  1456. X * and interpolate z value, texture coordinates and normal vector as 
  1457. X * we go. Call the shader and write into scanline buffer according to 
  1458. X * result on z-buffer test.
  1459. X */
  1460. static void
  1461. render_line(res, z_buffer, scanline, edge_list)
  1462. X    int            res;
  1463. X    double        *z_buffer;
  1464. X    unsigned char *scanline;
  1465. X    Edge          *edge_list;
  1466. {
  1467. X    double z, zstep;
  1468. X    double nx, nxstep;
  1469. X    double ny, nystep;
  1470. X    double nz, nzstep;
  1471. X    double u, ustep;
  1472. X    double v, vstep;
  1473. X    double w, wstep;
  1474. X    double ratio;
  1475. X    Color  color;
  1476. X    int    i, j, x, xstop;
  1477. X    Edge  *edgep, *next;
  1478. X    
  1479. X    edgep = edge_list;
  1480. X    next = NULL;
  1481. X    while (edgep != NULL) {
  1482. X        if (edgep->y != edgep->y_stop) {
  1483. X            next = edgep->next;
  1484. X            while (next->y == next->y_stop)
  1485. X                next = next->next;
  1486. X            x = (int)(edgep->x + 0.5);
  1487. X            xstop = (int)(next->x + 0.5);
  1488. X            z = edgep->z;
  1489. X            nx = edgep->nx;
  1490. X            ny = edgep->ny;
  1491. X            nz = edgep->nz;
  1492. X            u = edgep->u;
  1493. X            v = edgep->v;
  1494. X            w = edgep->w;
  1495. X            if (x < xstop) {
  1496. X                ratio = (double)(xstop - x);
  1497. X                zstep = (next->z - z) / ratio;
  1498. X                nxstep = (next->nx - nx) / ratio;
  1499. X                nystep = (next->ny - ny) / ratio;
  1500. X                nzstep = (next->nz - nz) / ratio;
  1501. X                ustep = (next->u - u) / ratio;
  1502. X                vstep = (next->v - v) / ratio;
  1503. X                wstep = (next->w - w) / ratio;
  1504. X            } else {
  1505. X                zstep = 0.0;
  1506. X                nxstep = nystep = nzstep = 0.0;
  1507. X                ustep = vstep = wstep = 0.0;
  1508. X            }
  1509. X            for (i = x, j = i * 3; i <= xstop; i++) {
  1510. X                if ((i >= 0) && (i < res) && (z >= 0.0) && (z <= 1.0)
  1511. X                    && (z < z_buffer[i])) {
  1512. X                    (*edgep->surface->shader)
  1513. X                        (nx, ny, nz, u, v, w,
  1514. X                         camera.vec, lightsrc_stack, 
  1515. X                         edgep->surface->surface, &color);
  1516. X                    scanline[j++] = (unsigned char)(color.red * 255.0 + 0.5);
  1517. X                    scanline[j++] = (unsigned char)(color.grn * 255.0 + 0.5);
  1518. X                    scanline[j++] = (unsigned char)(color.blu * 255.0 + 0.5);
  1519. X                    z_buffer[i] = z;
  1520. X                } else if (i >= res) {
  1521. X                    break;
  1522. X                } else {
  1523. X                    j += 3;
  1524. X                }
  1525. X                z += zstep;
  1526. X                nx += nxstep;
  1527. X                ny += nystep;
  1528. X                nz += nzstep;
  1529. X                u += ustep;
  1530. X                v += vstep;
  1531. X                w += wstep;
  1532. X            }
  1533. X        }
  1534. X        edgep = edgep->next;
  1535. X        if ((edgep == next) && (next != NULL))
  1536. X            edgep = edgep->next;
  1537. X    }
  1538. }
  1539. X
  1540. X
  1541. X
  1542. /*
  1543. X * Insert an edge into an edge list. Edges belonging to the same
  1544. X * polygon must be inserted sorted in x, so that edge pairs are
  1545. X * created.
  1546. X */
  1547. static Edge *
  1548. insert_edge(edge_list, edge, poly_found)
  1549. X    Edge *edge_list, *edge;
  1550. X    bool  poly_found;
  1551. {
  1552. X    if (edge_list == NULL) {
  1553. X        edge_list = edge;
  1554. X    edge->next = NULL;
  1555. X    } else if (edge_list->polygon == edge->polygon) {
  1556. X        if (edge_list->x > edge->x) {
  1557. X        edge->next = edge_list;
  1558. X        edge_list = edge;
  1559. X    } else if ((((int)(edge_list->x + 0.5)) == ((int)(edge->x + 0.5)))
  1560. X                   && (edge_list->xstep > edge->xstep)) {
  1561. X        edge->next = edge_list;
  1562. X        edge_list = edge;
  1563. X        } else {
  1564. X        edge_list->next = insert_edge(edge_list->next, edge, TRUE);
  1565. X        }
  1566. X    } else if (poly_found) {
  1567. X        edge->next = edge_list;
  1568. X        edge_list = edge;
  1569. X    } else {
  1570. X        edge_list->next = insert_edge(edge_list->next, edge, FALSE);
  1571. X    }
  1572. X
  1573. X    return edge_list;
  1574. }
  1575. X        
  1576. X
  1577. X
  1578. /*
  1579. X * Merge two edge lists.
  1580. X */
  1581. static Edge *
  1582. merge_edge_lists(list1, list2)
  1583. X    Edge *list1, *list2;
  1584. {
  1585. X    Edge *eref1, *eref2, *next;
  1586. X    
  1587. X    if (list2 == NULL)
  1588. X        return NULL;
  1589. X    eref1 = list1;
  1590. X    eref2 = list2;
  1591. X    do {
  1592. X        next = eref2->next;
  1593. X        eref1 = insert_edge(eref1, eref2, FALSE);
  1594. X    eref2 = next;
  1595. X    } while (eref2 != NULL);
  1596. X    return eref1;
  1597. }
  1598. X
  1599. X
  1600. X
  1601. /*
  1602. X * Allocate the needed buffers. Create a list of active edges and
  1603. X * move down the y-bucket, inserting and deleting edges from this
  1604. X * active list as we go. Call render_line for each scanline and
  1605. X * do an average filtering before writing the scanline to the result
  1606. X * file descriptor.
  1607. X */
  1608. static void
  1609. scan_and_render(xres, yres, image_file)
  1610. X    int  xres, yres;
  1611. X    FILE *image_file;
  1612. {
  1613. X    Edge          *active_list, *edgep, *edgep2;
  1614. X    double        *z_buffer;
  1615. X    unsigned char *scanline1, *scanline2, *stmp;
  1616. X    int            i, y, next_edge;
  1617. X    
  1618. X    z_buffer = (double *)calloc(xres, sizeof(double));
  1619. X    scanline1 = (unsigned char *)calloc(xres * 3, sizeof(unsigned char));
  1620. X    scanline2 = (unsigned char *)calloc(xres * 3, sizeof(unsigned char));
  1621. X
  1622. X    fprintf(image_file, "P6\n");
  1623. X    fprintf(image_file, "#Image rendered with SIPP %s\n", VERSION);
  1624. X    fprintf(image_file, "%d\n%d\n255\n", xres >> 1, yres >> 1);
  1625. X    y = yres - 1;
  1626. X    active_list = NULL;
  1627. X    stmp = scanline1;
  1628. X    while (y >= 0) {
  1629. X        active_list = merge_edge_lists(active_list, y_bucket[y].first);
  1630. X        next_edge = y - 1;
  1631. X        while (next_edge >=0 && y_bucket[next_edge].first == NULL)
  1632. X            next_edge--;
  1633. X        while (y > next_edge) {
  1634. X            init_buffers(xres, z_buffer, stmp);
  1635. X            render_line(xres, z_buffer, stmp, active_list);
  1636. X            if (stmp == scanline1)
  1637. X                stmp = scanline2;
  1638. X            else {
  1639. X                for (i = 0; i < (xres * 3); i += 6) {
  1640. X                    scanline1[i >> 1] = (scanline1[i] +
  1641. X                                         scanline1[i + 3] +
  1642. X                                         scanline2[i] +
  1643. X                                         scanline2[i + 3]) >> 2;
  1644. X                    scanline1[(i >> 1) + 1] = (scanline1[i + 1] +
  1645. X                                               scanline1[i + 4] +
  1646. X                                               scanline2[i + 1] +
  1647. X                                               scanline2[i + 4]) >> 2;
  1648. X                    scanline1[(i >> 1) + 2] = (scanline1[i + 2] +
  1649. X                                               scanline1[i + 5] +
  1650. X                                               scanline2[i + 2] +
  1651. X                                               scanline2[i + 5]) >> 2;
  1652. X                }
  1653. X                fwrite(scanline1, (xres >> 1) * 3, 1, image_file);
  1654. X                fflush(image_file);
  1655. X                stmp = scanline1;
  1656. X            }
  1657. X        if (active_list != NULL) {
  1658. X            edgep2 = active_list;
  1659. X            edgep = active_list->next;
  1660. X            while (edgep != NULL)
  1661. X                if (edgep->y <= (edgep->y_stop + 1)) {
  1662. X                        edgep2->next = edgep->next;
  1663. X                free(edgep);
  1664. X                    edgep = edgep2->next;
  1665. X            } else {
  1666. X                edgep2 = edgep;
  1667. X                edgep = edgep->next;
  1668. X            }
  1669. X              if (active_list->y <= (active_list->y_stop + 1)) {
  1670. X                edgep = active_list;
  1671. X            active_list = active_list->next;
  1672. X                free(edgep);
  1673. X            }
  1674. X            edgep = active_list;
  1675. X            while (edgep != NULL) {
  1676. X                edgep->y--;
  1677. X            edgep->x += edgep->xstep;
  1678. X            edgep->z += edgep->zstep;
  1679. X            edgep->nx += edgep->nxstep;
  1680. X            edgep->ny += edgep->nystep;
  1681. X            edgep->nz += edgep->nzstep;
  1682. X            edgep->u += edgep->ustep;
  1683. X            edgep->v += edgep->vstep;
  1684. X            edgep->w += edgep->wstep;
  1685. X            edgep = edgep->next;
  1686. X            }
  1687. X        }
  1688. X        y--;
  1689. X    }
  1690. X    }
  1691. X    free(z_buffer);
  1692. X    free(scanline1);
  1693. X    free(scanline2);
  1694. }
  1695. X
  1696. X
  1697. X
  1698. /*
  1699. X * Reset the averaged normals in the vertex tree P.
  1700. X */
  1701. static void
  1702. reset_normals(vref)
  1703. X    Vertex *vref;
  1704. {
  1705. X    if (vref != NULL) {
  1706. X        vref->a = 0;
  1707. X        vref->b = 0;
  1708. X        vref->c = 0;
  1709. X        reset_normals(vref->big);
  1710. X        reset_normals(vref->sml);
  1711. X    }
  1712. }
  1713. X
  1714. X
  1715. X
  1716. /*
  1717. X * Build a transformation matrix for transformation
  1718. X * into view coordinates. Perpective transformation
  1719. X * is also included
  1720. X */
  1721. static void
  1722. get_view_transf(mat)
  1723. X    double mat[4][4];
  1724. {
  1725. X    Vector tmp;
  1726. X    double transl[3];
  1727. X    double vy, vz;
  1728. X    double hither, yon;
  1729. X    double alfa, beta;
  1730. X    int i, j;
  1731. X    
  1732. X    /*
  1733. X     * First we need a translation so the origo
  1734. X     * of the view coordinat system is placed
  1735. X     * in the viewpoint.
  1736. X     */
  1737. X    transl[0] = -camera.x0;
  1738. X    transl[1] = -camera.y0;
  1739. X    transl[2] = -camera.z0;
  1740. X
  1741. X    /*
  1742. X     * Then we need a rotation that makes the
  1743. X     * up-vector point up, and alignes the sightline
  1744. X     * with the z-axis.
  1745. X     * This code might seem magic but the algebra behind
  1746. X     * it can be found in Jim Blinn's Corner in IEEE CG&A July 1988
  1747. X     */
  1748. X    VecCopy(tmp, camera.vec);
  1749. X    VecNegate(tmp);
  1750. X    vecnorm(&tmp);
  1751. X    vecnorm(&camera.up);
  1752. X    vz = VecDot(tmp, camera.up);
  1753. X    if ((vz * vz) > 1.0) {        /* this should not happen, but... */
  1754. X        vz = 1.0;
  1755. X    } else {
  1756. X        vy = sqrt(1.0 - vz * vz);
  1757. X        if (vy == 0.0) {          /* oops, the world collapses... */
  1758. X            vy = 1.0e10;
  1759. X            vz = 1.0;
  1760. X        } else {
  1761. X            vy = 1.0 / vy;
  1762. X        }
  1763. X    }
  1764. X
  1765. X    mat[0][2] = tmp.x;
  1766. X    mat[1][2] = tmp.y;
  1767. X    mat[2][2] = tmp.z;
  1768. X
  1769. X    VecScalMul(tmp, vz, tmp);
  1770. X    VecSub(tmp, camera.up, tmp);
  1771. X    mat[0][1] = tmp.x * vy;
  1772. X    mat[1][1] = tmp.y * vy;
  1773. X    mat[2][1] = tmp.z * vy;
  1774. X
  1775. X    mat[0][0] = mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1];
  1776. X    mat[1][0] = mat[2][1] * mat[0][2] - mat[2][2] * mat[0][1];
  1777. X    mat[2][0] = mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1];
  1778. X
  1779. X    /*
  1780. X     * Install the translation into the matrix.
  1781. X     * Note that it is PRE-multiplied into the matrix.
  1782. X     */
  1783. X    for (i = 0; i < 3; i++) {
  1784. X        mat[3][i] = 0.0;
  1785. X        for (j = 0; j < 3; j++) {
  1786. X            mat[3][i] += transl[j] * mat[j][i];
  1787. X        }
  1788. X    }
  1789. X     
  1790. X    /*
  1791. X     * Include the perspective transformation
  1792. X     * using heuristic values for hither and yon.
  1793. X     */
  1794. X    hither = VecLen(camera.vec) / ZCLIPF;
  1795. X    yon    = VecLen(camera.vec) * ZCLIPF;
  1796. X    alfa = camera.focal_ratio / (1.0 - hither / yon);
  1797. X    beta = -hither * alfa;
  1798. X
  1799. X    mat[0][3] = mat[0][2] * camera.focal_ratio;
  1800. X    mat[0][2] *= alfa;
  1801. X    mat[1][3] = mat[1][2] * camera.focal_ratio;
  1802. X    mat[1][2] *= alfa;
  1803. X    mat[2][3] = mat[2][2] * camera.focal_ratio;
  1804. X    mat[2][2] *= alfa;
  1805. X    mat[3][3] = mat[3][2] * camera.focal_ratio;
  1806. X    mat[3][2] = mat[3][2] * alfa + beta;
  1807. X
  1808. X    /*
  1809. X     * Since the screen coordinates are defined in a left handed
  1810. X     * coordinate system, we must switch the sign of the first
  1811. X     * column in the matrix to get appropriate signs of x-values.
  1812. X     */
  1813. X    mat[0][0] = -mat[0][0];
  1814. X    mat[1][0] = -mat[1][0];
  1815. X    mat[2][0] = -mat[2][0];
  1816. X    mat[3][0] = -mat[3][0];
  1817. }
  1818. X
  1819. X
  1820. /*
  1821. X * Free the memory used by an edge list.
  1822. X */
  1823. static void
  1824. delete_edges(edge_list)
  1825. X    Edge *edge_list;
  1826. {
  1827. X    Edge *edgeref1, *edgeref2;
  1828. X
  1829. X    edgeref1 = edge_list;
  1830. X    while (edgeref1 != NULL) {
  1831. X        edgeref2 = edgeref1->next;
  1832. X        free(edgeref1);
  1833. X        edgeref1 = edgeref2;
  1834. X    }
  1835. }
  1836. X
  1837. X
  1838. X
  1839. /*
  1840. X * Push the current transformation matrix on the matrix stack.
  1841. X */
  1842. static void
  1843. matrix_push()
  1844. {
  1845. X    struct tm_stack_t *new_tm;
  1846. X
  1847. X    new_tm = (struct tm_stack_t *)smalloc(sizeof(struct tm_stack_t));
  1848. X    MatCopy(&new_tm->mat, &curr_mat);
  1849. X    new_tm->next = tm_stack;
  1850. X    tm_stack     = new_tm;
  1851. }
  1852. X
  1853. X
  1854. /*
  1855. X * Pop the top of the matrix stack and make
  1856. X * it the new current transformation matrix.
  1857. X */
  1858. static void
  1859. matrix_pop()
  1860. {
  1861. X    struct tm_stack_t *tmp;
  1862. X
  1863. X    MatCopy(&curr_mat, &tm_stack->mat);
  1864. X    tmp = tm_stack;
  1865. X    tm_stack = tm_stack->next;
  1866. X    free(tmp);
  1867. }
  1868. X
  1869. X
  1870. X
  1871. /*
  1872. X * Traverse an object hierarchy, transform each object
  1873. X * according to its transformation matrix.
  1874. X * Transform all polygons in the object to view coordinates.
  1875. X * Build the edge lists in y_bucket.
  1876. X */
  1877. static void
  1878. traverse_object_tree(object, glob_view_mat, xres, yres)
  1879. X    Object *object;
  1880. X    double  glob_view_mat[4][4];
  1881. X    int     xres, yres;
  1882. {
  1883. X    Object  *objref;
  1884. X    Surface *surfref;
  1885. X    Polygon *polyref;
  1886. X    Vector   eyepoint, tmp;
  1887. X    double   loc_view_mat[4][4];
  1888. X
  1889. X
  1890. X    if (object == NULL) {
  1891. X        return;
  1892. X    }
  1893. X
  1894. X    for (objref = object; objref != NULL; objref = objref->next) {
  1895. X
  1896. X        matrix_push();
  1897. X        mat_mul(&curr_mat, &objref->transf, &curr_mat);
  1898. X        mat_mul34(loc_view_mat, &curr_mat, glob_view_mat);
  1899. X
  1900. X        tmp.x = camera.x0;
  1901. X        tmp.y = camera.y0;
  1902. X        tmp.z = camera.z0;
  1903. X
  1904. X        /*
  1905. X         * Do an inverse transformation of the viewpoint to use
  1906. X         * when doing backface culling (in calc_normals()).
  1907. X         */
  1908. X        tmp.x -= curr_mat.mat[3][0];
  1909. X        tmp.y -= curr_mat.mat[3][1];
  1910. X        tmp.z -= curr_mat.mat[3][2];
  1911. X        eyepoint.x = (tmp.x * curr_mat.mat[0][0] + tmp.y * curr_mat.mat[0][1]
  1912. X                      + tmp.z * curr_mat.mat[0][2]);
  1913. X        eyepoint.y = (tmp.x * curr_mat.mat[1][0] + tmp.y * curr_mat.mat[1][1]
  1914. X                      + tmp.z * curr_mat.mat[1][2]);
  1915. X        eyepoint.z = (tmp.x * curr_mat.mat[2][0] + tmp.y * curr_mat.mat[2][1]
  1916. X                      + tmp.z * curr_mat.mat[2][2]);
  1917. X
  1918. X        for (surfref = objref->surfaces; surfref != NULL; 
  1919. X             surfref = surfref->next) {
  1920. X
  1921. X            calc_normals(surfref->polygons, eyepoint);
  1922. X
  1923. X            for (polyref = surfref->polygons; polyref != NULL; 
  1924. X                 polyref = polyref->next) {
  1925. X
  1926. X                if (!polyref->backface) {
  1927. X                    transf_vertices(polyref->vertices, surfref, loc_view_mat, 
  1928. X                                    &curr_mat, (double)xres, (double)yres);
  1929. X                }
  1930. X
  1931. X            }
  1932. X            reset_normals(surfref->vertices);
  1933. X
  1934. X        }
  1935. X        traverse_object_tree(objref->sub_obj, glob_view_mat, xres, yres);
  1936. X        matrix_pop();
  1937. X    }
  1938. }
  1939. X
  1940. X
  1941. X
  1942. /*
  1943. X * Recursively traverse the rendering database (preorder).
  1944. X * Call traverse_object_tree for each object.
  1945. X */
  1946. static void
  1947. traverse_object_db(obj_root, view_mat, xres, yres)
  1948. X    Inst_object *obj_root;
  1949. X    double       view_mat[4][4];
  1950. X    int          xres, yres;
  1951. {
  1952. X    if (obj_root != NULL) {
  1953. X        traverse_object_tree(obj_root->object, view_mat, xres, yres);
  1954. X        traverse_object_db(obj_root->sml, view_mat, xres, yres);
  1955. X        traverse_object_db(obj_root->big, view_mat, xres, yres);
  1956. X    }
  1957. }
  1958. X
  1959. X
  1960. X
  1961. X
  1962. /*
  1963. X * "Main" function in rendering. Allocate y-bucket, transform vertices
  1964. X * into viewing coordinates, make edges and sort them into the y-bucket.
  1965. X * Call scan_and_render to do the real work.
  1966. X */
  1967. void
  1968. render_image(xres, yres, image_file)
  1969. X    int   xres, yres;
  1970. X    FILE *image_file;
  1971. {
  1972. X    double      matrix[4][4];
  1973. X    int         i;
  1974. X
  1975. X    y_bucket = (Bucket *)calloc(yres << 1, sizeof(Bucket));
  1976. X
  1977. X    get_view_transf(matrix);
  1978. X    MatCopy(&curr_mat, &ident_matrix);
  1979. X    
  1980. X    traverse_object_db(object_db, matrix, xres, yres);
  1981. X
  1982. X    vecnorm(&camera.vec);
  1983. X    scan_and_render(xres << 1, yres << 1, image_file);
  1984. X    view_vec_eval();
  1985. X
  1986. X    for (i = 0; i < (yres << 1); i++)
  1987. X        delete_edges(y_bucket[i].first);
  1988. X    free(y_bucket);
  1989. }
  1990. X
  1991. X
  1992. X
  1993. /*============= Functions that handles global initializations==============*/
  1994. X
  1995. /*
  1996. X * Necessary initializations.
  1997. X */
  1998. void
  1999. sipp_init()
  2000. {
  2001. X    vertex_tree    = NULL;
  2002. X    vertex_stack   = NULL;
  2003. X    poly_stack     = NULL;
  2004. X    object_db      = NULL;
  2005. X    lightsrc_stack = NULL;
  2006. X    first_vertex   = 0;
  2007. X    viewpoint(0.0, 0.0, 10.0,  0.0, 0.0, 0.0,  0.0, 1.0, 0.0,  0.25);
  2008. }
  2009. SHAR_EOF
  2010. chmod 0644 libsipp/sipp.c ||
  2011. echo 'restore of libsipp/sipp.c failed'
  2012. Wc_c="`wc -c < 'libsipp/sipp.c'`"
  2013. test 52154 -eq "$Wc_c" ||
  2014.     echo 'libsipp/sipp.c: original size 52154, current size' "$Wc_c"
  2015. fi
  2016. true || echo 'restore of libsipp/sipp.h failed'
  2017. echo End of part 3, continue with part 4
  2018. exit 0
  2019.  
  2020. -- 
  2021. Inge Wallin               | Thus spake the master programmer:               |
  2022.                           |      "After three days without programming,     |
  2023. ingwa@isy.liu.se          |       life becomes meaningless."                |
  2024.                           | Geoffrey James: The Tao of Programming.         |
  2025.  
  2026.  
  2027. exit 0 # Just in case...
  2028. -- 
  2029. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2030. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2031. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2032. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2033.